﻿///////////////////////////////////////////////////////////////////////////////
// File:        SocketManager.hpp
// Author:      671643387@qq.com
// Date:        2016年1月5日 下午5:44:04
// Description:
///////////////////////////////////////////////////////////////////////////////

#ifndef NET_SOCKETMANAGER_HPP_
#define NET_SOCKETMANAGER_HPP_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

#include <vector>
#include <string>
#include <boost/noncopyable.hpp>
#include <boost/unordered_map.hpp>
#include <fog/Typedef.hpp>
#include <fog/thread/Mutex.hpp>
#include <fog/thread/LockGuard.hpp>
#include <fog/net/SocketFactory.hpp>
#include <fog/net/SocketThread.hpp>

namespace fog
{
    namespace net
    {
        class SocketManager : public boost::noncopyable
        {
        public:
            enum State
            {
                kNotReady,
                kReady,
                kRunning,
                kExiting,
                kExit
            };

        public:
            SocketManager(SocketFactoryPtr factory = SocketFactoryPtr());
            ~SocketManager(void);

            bool open(const std::string &addr, short port, int backlog, int threads = 0);
            void join(void);
            void close(void);

        private:
            friend class Socket;

        private:
            void doCloseSocket(Socket *s);
            SocketThreadPtr &findMostFreeThread(void);

        private:
            static void onAccept(evutil_socket_t sock, short event, void* arg);
            void doAccept(void);

        private:
            typedef std::vector<SocketThreadPtr>                SocketThreadArray;
            typedef boost::unordered_map<int, SocketPtr>        SocketMap;

        private:
            State state_;

            std::string address_;
            short port_;
            int backlog_;
            int threads_;

            int connIdGen_;
            evutil_socket_t sListen_;
            struct event *evListen_;

            SocketFactoryPtr sFactory_;

            SocketThreadArray sockThreads_;
            SocketMap sockMap_;
            thread::Mutex sockMapLock_;

            thread::Mutex acceptLock_;
        };
    }
}

#endif /* NET_SOCKETMANAGER_HPP_ */
